package com.sc.common.shiro.authenticator;

import com.sc.common.shiro.token.PersonalUsernamePasswordToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;

import java.util.ArrayList;
import java.util.Collection;

/*readme
    自定义验证器，用于分发Token给Realm用于验证登录
 */
public class PersonalModularRealmAuthenticator extends ModularRealmAuthenticator {
    @Override
    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        //调用方法判断Realm是否为空（有没有配置Realm）
        //没有会抛出异常
        assertRealmsConfigured();
        //将令牌强制转换成其子类--自定义的令牌
        PersonalUsernamePasswordToken PersonalToken = (PersonalUsernamePasswordToken) authenticationToken;
        //获取登录类型，用于分发
        String loginType = PersonalToken.getLoginType();
        //获取所有Realm的集合
        Collection<Realm> realms = getRealms();
        //创建一个集合，用于获取符合对应loginType的Realm
        //使用类名进行判断，所以Realm的命名要和loginType一一对应
        //例如：学生登录的loginType="Student",那么验证学生身份信息的Realm就应为StudentRealm
        //注：集合是为了防止可能存在多个Realm的情况，我们这里只会一一对应，但是还是使用集合
        Collection<Realm> typeRealms = new ArrayList<>();

        //将符合要求的存入typeRealms中
        for (Realm realm : realms) {
            if (realm.getName().contains(loginType))
                typeRealms.add(realm);
        }

        //与源码中一样，判断单还是多个Realm
        if (typeRealms.size() == 1)
            return doSingleRealmAuthentication(typeRealms.iterator().next(), PersonalToken);
        else
            return doMultiRealmAuthentication(typeRealms, PersonalToken);
    }
}
